/// 1. trait_bound语法
/// 2. 指定多个trait_bound
/// 3. 返回trait的类型

/***
// trait作为参数
fn print_information(item: impl GetInformation) { // 第一种：直接作为参数的写法
fn print_information<T: GetInformation>(item: T) { // 第二种：使用trait_bound的写法
    println!("name = {}", item.get_name());
    println!("age = {}", item.gey_age());
}
 */
trait GetName {
    fn get_name(&self) -> &String;
}
trait GetAge {
    fn get_age(&self) -> u32;
}
// 实现trait
#[derive(Debug)]
pub struct Student {
    pub name: String,
    pub age: u32,
}
impl GetName for Student {
    fn get_name(&self) -> &String {
        &self.name
    }
}
impl GetAge for Student {
    fn get_age(&self) -> u32 {
        self.age
    }
}

fn print_information<T: GetName + GetAge>(item: T) { // 第二种：使用trait_bound的写法
    println!("name = {}", item.get_name());
    println!("age = {}", item.get_age());
}
fn _print_information1<T>(item: T)
where T: GetName+GetAge { // 第三种：使用trait_bound的写法
    println!("name = {}", item.get_name());
    println!("age = {}", item.get_age());
}

// 作为函数的返回 impl GetAge返回这个trait
fn produce_item_with_age() -> impl GetAge + std::fmt::Debug {
    Student {
        name: String::from("小小"),
        age: 12,
    }
}

#[derive(Debug)]
pub struct Teacher {
    pub name: String,
    pub age: u32,
}
impl GetAge for Teacher {
    fn get_age(&self) -> u32 {
        self.age
    }
}
impl GetName for Teacher {
    fn get_name(&self) -> &String {
        &self.name
    }
}

/// - 因为Student和Teacher的类型不一样，所以执行这个代码时会报错
/// - 为什么类型不一样：因为Student和Teacher在不同的地址上，Rust检查存在安全问题，所以会报错
// fn produce_item_with_age2() -> impl GetAge {
//     let is_true = true;
//
//     if is_true {
//         Student {
//             name: String::from("小小"),
//             age: 12,
//         }
//     } else {
//         Teacher {
//             name: String::from("张老师"),
//             age: 19,
//         }
//     }
// }
fn main() {
    let s = Student{name: "张同学".to_string(), age: 12};
    print_information(s);

    let s1 = produce_item_with_age();
    println!("{:?}", s1);
    println!("Hello, world!");
}
